Notebook for generating mutual rank (MR) clusters
library(boxr)
Welcome to boxr 0.3.4.99999!
Bug reports & Getting Help: https://github.com/brendan-R/boxr/issues
library(magrittr)
library(knitr)
library(limma)
library(snowfall)
Loading required package: snow
library(igraph)
Attaching package: ‘igraph’
The following object is masked from ‘package:magrittr’:
%>%
The following objects are masked from ‘package:stats’:
decompose, spectrum
The following object is masked from ‘package:base’:
union
box_auth()
Reading client id from .Renviron
Reading client secret from .Renviron
Auto-refreshing stale OAuth token.
boxr: Authenticated at box.com as Julin Maloof (jnmaloof@ucdavis.edu)
box_setwd(24503987860)
box.com working directory changed to 'BrapaNetworks'
id: 24503987860
tree: All Files/BrapaNetworks
owner: jnmaloof@ucdavis.edu
contents: 9 files, 0 folders
box_ls()
box.com remote object list (9 objects)
Summary of first 9:
name type id size
1 Brapa2011BayesHeight_blups.csv file 164446516413 15 kB
2 Brapa2012BayesHeight_blups.csv file 164446639332 28 kB
3 Brapa_V1.5_annotated.csv.gz file 163054185089 2.7 MB
4 brassica_gene_clusters.RData file 164456845216 110 kB
5 CountsVoom.Rdata file 162362592785 240 MB
6 NormalizedCounts.RData file 162341539458 100 MB
7 RIL_TMM_CPM.csv file 162352229544 630 MB
8 RIL_v1.5_mapping.tsv file 162218089685 110 MB
9 test.Rdata file 162921069376 64 B
owner
1 jnmaloof@ucdavis.edu
2 jnmaloof@ucdavis.edu
3 jnmaloof@ucdavis.edu
4 jnmaloof@ucdavis.edu
5 jnmaloof@ucdavis.edu
6 jnmaloof@ucdavis.edu
7 jnmaloof@ucdavis.edu
8 jnmaloof@ucdavis.edu
9 jnmaloof@ucdavis.edu
Use as.data.frame() to extract full results.
First attempt, use RIL means
Get data
annotation <- read_csv("~/Box Sync/BrapaNetworks/Brapa_V1.5_annotated.csv.gz")
Error: could not find function "read_csv"
Summarize means
save(voom.fit,fil="~/Box Sync/BrapaNetworks/voom.fit.Rdata")
Error in save(voom.fit, fil = "~/Box Sync/BrapaNetworks/voom.fit.Rdata") :
object ‘~/Box Sync/BrapaNetworks/voom.fit.Rdata’ not found
RIL.coefs <- grep("RIL",colnames(coef(voom.fit)))
RIL.pvals <- topTable(voom.fit,coef = RIL.coefs,number = Inf)
sum(RIL.pvals$adj.P.Val<0.05)
[1] 26721
sum(RIL.pvals$adj.P.Val<10e-10)
[1] 16596
So pretty much everything is highly significant
Start by taking the top 10000
genes.of.interest <- row.names(RIL.pvals)[1:10000]
expr.data <- voom.fit$coefficients[genes.of.interest,]
expr.data <- expr.data[,-grep("trt",colnames(expr.data))]
dim(expr.data)
[1] 10000 124
head(expr.data[,1:6])
(Intercept) pdata$RILRIL_103 pdata$RILRIL_104 pdata$RILRIL_113
Bra001964 1.082235 -4.0321896 -4.091759090 3.6994071
Bra002728 5.767475 -0.5505380 -0.380674984 -3.2039164
Bra002785 7.202490 -0.4198373 -0.037837754 -1.9963410
Bra004960 4.733936 -3.8185006 -0.004181862 -0.2564264
Bra006384 4.969959 -6.8228958 -7.276735466 -0.3784078
Bra006411 -2.499584 6.3062481 -0.470837158 0.1143828
pdata$RILRIL_115 pdata$RILRIL_12
Bra001964 0.01722016 0.64266465
Bra002728 -0.60526951 -0.81853556
Bra002785 -0.04677711 -0.05993573
Bra004960 0.14101788 -0.22825526
Bra006384 -8.39926386 -7.41766487
Bra006411 -0.72175621 -1.10891611
expr.data[,-1] <- expr.data[,-1] + expr.data[,1] # add the intercept to the coefficients
colnames(expr.data) <- sub("pdata$RIL","",colnames(expr.data),fixed=TRUE)
head(expr.data[,1:6])
(Intercept) RIL_103 RIL_104 RIL_113 RIL_115 RIL_12
Bra001964 1.082235 -2.9499545 -3.009524 4.781642 1.099455 1.724900
Bra002728 5.767475 5.2169367 5.386800 2.563558 5.162205 4.948939
Bra002785 7.202490 6.7826522 7.164652 5.206149 7.155712 7.142554
Bra004960 4.733936 0.9154359 4.729755 4.477510 4.874954 4.505681
Bra006384 4.969959 -1.8529365 -2.306776 4.591552 -3.429305 -2.447706
Bra006411 -2.499584 3.8066642 -2.970421 -2.385201 -3.221340 -3.608500
Get Rob’s Data
blups2011 <- box_read_csv(164446516413)
Remote file '/var/folders/xr/9cbydt955pj42zfq6mc_y5g40000gn/T//Rtmp7o2lKa/Brapa2011BayesHeight_blups.csv' read into memory as an object of class data.frame
blups2012 <- box_read_csv(164446639332)
Remote file '/var/folders/xr/9cbydt955pj42zfq6mc_y5g40000gn/T//Rtmp7o2lKa/Brapa2012BayesHeight_blups.csv' read into memory as an object of class data.frame
blups2011$Line %<>% paste("RIL",.,sep="_")
blups2012$Line %<>% paste("RIL",.,sep="_")
blups2011 %<>% subset(select=!grepl("V1|individual|blk|trt|treat",colnames(.)))
blups2012 %<>% subset(select=!grepl("V1|individual|blk|trt|treat",colnames(.)))
head(blups2011)
head(blups2012)
Merge Data
expr.blup.2011 <- merge(blups2011,t(expr.data),by.x="Line",by.y=0)
expr.blup.2012 <- merge(blups2012,t(expr.data),by.x="Line",by.y=0)
head(expr.blup.2011)
head(expr.blup.2012)
Correlation
expr.blup.2011.cor <- cor(expr.blup.2011[,-1])
expr.blup.2012.cor <- cor(expr.blup.2012[,-1])
Mutual Rank
sfStop()
Stopping cluster
save(blups2011,blups2012,voom.fit,expr.blup.2011, expr.blup.2012,expr.blup.2011.mr, expr.blup.2012.mr,file = "~/Box Sync/BrapaNetworks/MR.Rdata")
Get graphs at different MR
First: define some functions
Get blup networks at different MR thresholds
Use different MR thresholds of 10 to 210 (absolute values) to build the network (genes with a correlation higher than the threshold were considered connected). I then subset the network to take all genes “directly” connected to LFY.
plots
null device
1
null device
1
LS0tCnRpdGxlOiAiTVIgQ2x1c3RlcmluZyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKTm90ZWJvb2sgZm9yIGdlbmVyYXRpbmcgbXV0dWFsIHJhbmsgKE1SKSBjbHVzdGVycwoKYGBge3J9CmxpYnJhcnkoYm94cikKbGlicmFyeShtYWdyaXR0cikKbGlicmFyeShrbml0cikKbGlicmFyeShsaW1tYSkKbGlicmFyeShzbm93ZmFsbCkKbGlicmFyeShpZ3JhcGgpCmJveF9hdXRoKCkKYm94X3NldHdkKDI0NTAzOTg3ODYwKQpib3hfbHMoKQpgYGAKCiMjIyBGaXJzdCBhdHRlbXB0LCB1c2UgUklMIG1lYW5zCkdldCBkYXRhCmBgYHtyfQojYm94X2xvYWQoMTYyMzYyNTkyNzg1KQpsb2FkKCJ+L0JveCBTeW5jL0JyYXBhTmV0d29ya3MvQ291bnRzVm9vbS5SZGF0YSIpCmFubm90YXRpb24gIDwtIHJlYWQuY3N2KCJ+L0JveCBTeW5jL0JyYXBhTmV0d29ya3MvQnJhcGFfVjEuNV9hbm5vdGF0ZWQuY3N2Lmd6IikKYGBgCgpTdW1tYXJpemUgbWVhbnMKYGBge3J9CnN0cihjb3VudHMudm9vbSkKc3VtbWFyeShjb3VudHMudm9vbSkKdm9vbS5maXQgPC0gbG1GaXQoY291bnRzLnZvb20sZGVzaWduPWNvdW50cy52b29tJGRlc2lnbikgI2FkZGl0aXZlIGRlc2lnbiBpcyBhbHJlYWR5IHRoZXJlCnZvb20uZml0IDwtIGVCYXllcyh2b29tLmZpdCkKc2F2ZSh2b29tLmZpdCxmaWxlPSJ+L0JveCBTeW5jL0JyYXBhTmV0d29ya3Mvdm9vbS5maXQuUmRhdGEiKQpgYGAKCgpgYGB7cn0KUklMLmNvZWZzIDwtIGdyZXAoIlJJTCIsY29sbmFtZXMoY29lZih2b29tLmZpdCkpKQpSSUwucHZhbHMgPC0gdG9wVGFibGUodm9vbS5maXQsY29lZiA9IFJJTC5jb2VmcyxudW1iZXIgPSBJbmYpCnN1bShSSUwucHZhbHMkYWRqLlAuVmFsPDAuMDUpCnN1bShSSUwucHZhbHMkYWRqLlAuVmFsPDEwZS0xMCkgCmBgYApTbyBwcmV0dHkgbXVjaCBldmVyeXRoaW5nIGlzIGhpZ2hseSBzaWduaWZpY2FudAoKU3RhcnQgYnkgdGFraW5nIHRoZSB0b3AgMTAwMDAKCmBgYHtyfQpnZW5lcy5vZi5pbnRlcmVzdCA8LSByb3cubmFtZXMoUklMLnB2YWxzKVsxOjEwMDAwXQpleHByLmRhdGEgPC0gdm9vbS5maXQkY29lZmZpY2llbnRzW2dlbmVzLm9mLmludGVyZXN0LF0KZXhwci5kYXRhIDwtIGV4cHIuZGF0YVssLWdyZXAoInRydCIsY29sbmFtZXMoZXhwci5kYXRhKSldCmRpbShleHByLmRhdGEpCmhlYWQoZXhwci5kYXRhWywxOjZdKQpgYGAKCmBgYHtyfQpleHByLmRhdGFbLC0xXSA8LSBleHByLmRhdGFbLC0xXSArIGV4cHIuZGF0YVssMV0gIyBhZGQgdGhlIGludGVyY2VwdCB0byB0aGUgY29lZmZpY2llbnRzCmNvbG5hbWVzKGV4cHIuZGF0YSkgPC0gc3ViKCJwZGF0YSRSSUwiLCIiLGNvbG5hbWVzKGV4cHIuZGF0YSksZml4ZWQ9VFJVRSkKaGVhZChleHByLmRhdGFbLDE6Nl0pCmBgYAoKR2V0IFJvYidzIERhdGEKYGBge3J9CmJsdXBzMjAxMSA8LSBib3hfcmVhZF9jc3YoMTY0NDQ2NTE2NDEzKQpibHVwczIwMTIgPC0gYm94X3JlYWRfY3N2KDE2NDQ0NjYzOTMzMikKYmx1cHMyMDExJExpbmUgJTw+JSBwYXN0ZSgiUklMIiwuLHNlcD0iXyIpCmJsdXBzMjAxMiRMaW5lICU8PiUgcGFzdGUoIlJJTCIsLixzZXA9Il8iKQpibHVwczIwMTEgJTw+JSBzdWJzZXQoc2VsZWN0PSFncmVwbCgiVjF8aW5kaXZpZHVhbHxibGt8dHJ0fHRyZWF0Iixjb2xuYW1lcyguKSkpCmJsdXBzMjAxMiAlPD4lIHN1YnNldChzZWxlY3Q9IWdyZXBsKCJWMXxpbmRpdmlkdWFsfGJsa3x0cnR8dHJlYXQiLGNvbG5hbWVzKC4pKSkKaGVhZChibHVwczIwMTEpCmhlYWQoYmx1cHMyMDEyKQpgYGAKCk1lcmdlIERhdGEKYGBge3J9CmV4cHIuYmx1cC4yMDExIDwtIG1lcmdlKGJsdXBzMjAxMSx0KGV4cHIuZGF0YSksYnkueD0iTGluZSIsYnkueT0wKQpleHByLmJsdXAuMjAxMiA8LSBtZXJnZShibHVwczIwMTIsdChleHByLmRhdGEpLGJ5Lng9IkxpbmUiLGJ5Lnk9MCkKaGVhZChleHByLmJsdXAuMjAxMSkKaGVhZChleHByLmJsdXAuMjAxMikKYGBgCgpDb3JyZWxhdGlvbgpgYGB7cn0KZXhwci5ibHVwLjIwMTEuY29yIDwtIGNvcihleHByLmJsdXAuMjAxMVssLTFdKQpleHByLmJsdXAuMjAxMi5jb3IgPC0gY29yKGV4cHIuYmx1cC4yMDEyWywtMV0pCmBgYAoKTXV0dWFsIFJhbmsKYGBge3J9CnNmSW5pdChwYXJhbGxlbCA9IFRSVUUsIGNwdXM9NCkKCmV4cHIuYmx1cC4yMDExLnJhbmsgPC0gc2ZBcHBseShleHByLmJsdXAuMjAxMS5jb3IsMixmdW5jdGlvbih4KSByYW5rKC1hYnMoeCkpKQpleHByLmJsdXAuMjAxMS5yYW5rWzE6MTAsMToxMF0KZXhwci5ibHVwLjIwMTEubXIgPC0gc3FydChleHByLmJsdXAuMjAxMS5yYW5rKnQoZXhwci5ibHVwLjIwMTEucmFuaykpCmV4cHIuYmx1cC4yMDExLm1yWzE6MTAsMToxMF0KCmV4cHIuYmx1cC4yMDEyLnJhbmsgPC0gc2ZBcHBseShleHByLmJsdXAuMjAxMi5jb3IsMixmdW5jdGlvbih4KSByYW5rKC1hYnMoeCkpKQpleHByLmJsdXAuMjAxMi5yYW5rWzE6MTAsMToxMF0KZXhwci5ibHVwLjIwMTIubXIgPC0gc3FydChleHByLmJsdXAuMjAxMi5yYW5rKnQoZXhwci5ibHVwLjIwMTIucmFuaykpCmV4cHIuYmx1cC4yMDEyLm1yWzE6MTAsMToxMF0KCnNmU3RvcCgpCmBgYAoKCmBgYHtyfQpzYXZlKGJsdXBzMjAxMSxibHVwczIwMTIsdm9vbS5maXQsZXhwci5ibHVwLjIwMTEsIGV4cHIuYmx1cC4yMDEyLGV4cHIuYmx1cC4yMDExLm1yLCBleHByLmJsdXAuMjAxMi5tcixmaWxlID0gIn4vQm94IFN5bmMvQnJhcGFOZXR3b3Jrcy9NUi5SZGF0YSIpCmBgYAoKR2V0IGdyYXBocyBhdCBkaWZmZXJlbnQgTVIKCkZpcnN0OiBkZWZpbmUgc29tZSBmdW5jdGlvbnMKIApgYGB7ciBtcl9zdWJncmFwaHMsIGVjaG89RkFMU0UsIGNhY2hlLmxhenk9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGV2YWw9VFJVRSB9CmxvYWQoIn4vQm94IFN5bmMvQnJhcGFOZXR3b3Jrcy9NUi5SZGF0YSIpCmdldC5tci5zdWJncmFwaCA8LSBmdW5jdGlvbihtci5jdXRvZmYsbXIubWF0cml4LGFubm90YXRpb249TkEsbmVpZ2hib3Job29kLG9yZGVyPTEpIHsKICAjZnVuY3Rpb24gdG8gZXh0cmFjdCBMRlkgZ3JhcGggYXQgYSBzcGVjaWZpY2VkIGNvcnJlbGF0aW9uIGN1dG9mZgogIGdlbmUubXIudG1wIDwtIG1yLm1hdHJpeAogIGdlbmUubXIudG1wW2FicyhnZW5lLm1yLnRtcCkgPiBtci5jdXRvZmZdIDwtIDAKICBnZW5lLm1yLnRtcFtpcy5uYShnZW5lLm1yLnRtcCldIDwtIDAgI2ltcG9ydGFudCEgb3RoZXJ3aXNlIHZlcnRpY2VzIHdpdGggTkEgZWRnZXMgYXJlIGNvbm5lY3RlZAogIAogIGdlbmUuZ3JhcGggPC0gZ3JhcGguYWRqYWNlbmN5KGFkam1hdHJpeCA9IGdlbmUubXIudG1wLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1vZGU9InVuZGlyZWN0ZWQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdlaWdodGVkPSJtciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlhZz1GQUxTRSkKICAKICAjY2x1c3QubWVtYmVyc2hpcCA8LSBjbHVzdGVycyhnZW5lLmdyYXBoKSRtZW1iZXJzaGlwCiAgCiAgI2NvbGJhciA8LSByYWluYm93KG1heChjbHVzdC5tZW1iZXJzaGlwKSsxKSAgICAgICAgICAgICAgICAgI2RlZmluZSBjb2xvcnMKICAjVihnZW5lLmdyYXBoKSRjb2xvciA8LSBjb2xiYXJbY2x1c3QubWVtYmVyc2hpcCsxXSAgICAgICAgICAgICAjYXNzaWduIGNvbG9ycyB0byBub2RlcwogIHN1Yi5ncmFwaHMgPC0gZ3JhcGgubmVpZ2hib3Job29kKGdlbmUuZ3JhcGgsb3JkZXI9b3JkZXIsbm9kZXM9bmVpZ2hib3Job29kKSAjZm9yIGVhY2ggbmRvZSBvZiBpbnRlcmVzdCBnZXQgYWxsIG90aGVyIG5vZGVzIHdpdGhpbiBvcmRlciBvZiAxCiAgCiAgI2dldCBjb21ibmluZWQgbGlzdCBvZiB2ZXJ0aWNlcy4uLgogIAogIHN1Yi52ZXJ0aWNlcyA8LSB1bmlxdWUobmFtZXModW5saXN0KHNhcHBseShzdWIuZ3JhcGhzLCBWKSkpKQogIAogIGNvbWJpbmVkLnN1Yi5ncmFwaCA8LSBpbmR1Y2VkX3N1YmdyYXBoKGdlbmUuZ3JhcGgsc3ViLnZlcnRpY2VzKQogIAogIFYoY29tYmluZWQuc3ViLmdyYXBoKSRjb2xvciA8LSAibGlnaHRibHVlIgogIFYoY29tYmluZWQuc3ViLmdyYXBoKVtuZWlnaGJvcmhvb2RdJGNvbG9yIDwtICJyZWQiCiAgaWYoIWlzLm5hKGFubm90YXRpb24pKSBWKGNvbWJpbmVkLnN1Yi5ncmFwaCkkZ2VuZSA8LSBhbm5vdGF0aW9uJFNZTUJPTFttYXRjaChWKGNvbWJpbmVkLnN1Yi5ncmFwaCkkbmFtZSxhbm5vdGF0aW9uJFRBSVIpXQogIGxpc3QoY3V0b2ZmPW1yLmN1dG9mZixncmFwaD1jb21iaW5lZC5zdWIuZ3JhcGgpCiAgfQpgYGAKCiMjIEdldCBibHVwIG5ldHdvcmtzIGF0IGRpZmZlcmVudCBNUiB0aHJlc2hvbGRzClVzZSBkaWZmZXJlbnQgTVIgdGhyZXNob2xkcyBvZiAxMCB0byAyMTAgKGFic29sdXRlIHZhbHVlcykgdG8gYnVpbGQgdGhlIG5ldHdvcmsgKGdlbmVzIHdpdGggYSBjb3JyZWxhdGlvbiBoaWdoZXIgdGhhbiB0aGUgdGhyZXNob2xkIHdlcmUgY29uc2lkZXJlZCBjb25uZWN0ZWQpLiAgSSB0aGVuIHN1YnNldCB0aGUgbmV0d29yayB0byB0YWtlIGFsbCBnZW5lcyAiZGlyZWN0bHkiIGNvbm5lY3RlZCB0byBMRlkuCgpgYGB7ciBsZnlfc3ViLCBlY2hvPUZBTFNFLCBldmFsPUZBTFNFfQpjdXRvZmZzIDwtIGMoMTAsMjAsMzAsNTAsODAsMTAwLDEzMCwyMTApCmJsdXAubXIuZ3JhcGhzLjIwMTEgPC0gbGFwcGx5KGN1dG9mZnMsIGdldC5tci5zdWJncmFwaCwgbXIubWF0cml4ID0gZXhwci5ibHVwLjIwMTEubXIsIGFubm90YXRpb249IE5BLCBuZWlnaGJvcmhvb2QgPSBjb2xuYW1lcyhibHVwczIwMTEpWy0xXSkKbmFtZXMoYmx1cC5tci5ncmFwaHMuMjAxMSkgPC0gc2FwcGx5KGJsdXAubXIuZ3JhcGhzLjIwMTEsIGZ1bmN0aW9uKHgpIHBhc3RlKCJibHVwLm1yLmdyYXBoLjIwMTEiLHgkY3V0b2ZmLHNlcD0iLiIpKQoKYmx1cC5tci5ncmFwaHMuMjAxMiA8LSBsYXBwbHkoY3V0b2ZmcywgZ2V0Lm1yLnN1YmdyYXBoLCBtci5tYXRyaXggPSBleHByLmJsdXAuMjAxMi5tciwgYW5ub3RhdGlvbj0gTkEsIG5laWdoYm9yaG9vZCA9IGNvbG5hbWVzKGJsdXBzMjAxMilbLTFdKQpuYW1lcyhibHVwLm1yLmdyYXBocy4yMDEyKSA8LSBzYXBwbHkoYmx1cC5tci5ncmFwaHMuMjAxMiwgZnVuY3Rpb24oeCkgcGFzdGUoImJsdXAubXIuZ3JhcGguMjAxMiIseCRjdXRvZmYsc2VwPSIuIikpCmBgYAoKIyMgcGxvdHMKCmBgYHtyIHBsb3QsIGVjaG89RkFMU0UsIGNhY2hlPVRSVUV9CmN1dG9mZj0yMDAKcGRmKCJibHVwLm1yLnBsb3RzLjIwMTEucGRmIixoZWlnaHQ9MTIsd2lkdGg9MTIpCnJlc3VsdCA8LSBzYXBwbHkoYmx1cC5tci5ncmFwaHMuMjAxMSxmdW5jdGlvbiAoYmx1cC5ncmFwaCkgewogIGlmKGJsdXAuZ3JhcGgkY3V0b2ZmIDw9IGN1dG9mZikgewogICAgRShibHVwLmdyYXBoJGdyYXBoKSR3ZWlnaHQgPC0gcmFuayhFKGJsdXAuZ3JhcGgkZ3JhcGgpJG1yKV4oMS80KQogICAgcGxvdChibHVwLmdyYXBoJGdyYXBoLAogICAgICAgICBsYXlvdXQgPSBsYXlvdXRfd2l0aF9raywgCiAgICAgICAgIHZlcnRleC5sYWJlbCA9ICNpZmVsc2UoaXMubmEoVihibHVwLmdyYXBoJGdyYXBoKSRnZW5lKXxWKGJsdXAuZ3JhcGgkZ3JhcGgpJGdlbmU9PSIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVihibHVwLmdyYXBoJGdyYXBoKSRuYW1lICwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgICBWKGJsdXAuZ3JhcGgkZ3JhcGgpJGdlbmUpLAogICAgICAgICB2ZXJ0ZXgubGFiZWwuY2V4PTEsCiAgICAgICAgIG1haW49cGFzdGUoIk1SIGN1dG9mZiA9IixzdWIoImJsdXAubXIuZ3JhcGguIiwiIixibHVwLmdyYXBoJGN1dG9mZixmaXhlZD1UKSkpCiAgICBybShibHVwLmdyYXBoKQogICAgfQogIH0pCmRldi5vZmYoKQoKY3V0b2ZmPTIwMApwZGYoImJsdXAubXIucGxvdHMuMjAxMi5wZGYiLGhlaWdodD0xMix3aWR0aD0xMikKcmVzdWx0IDwtIHNhcHBseShibHVwLm1yLmdyYXBocy4yMDEyLGZ1bmN0aW9uIChibHVwLmdyYXBoKSB7CiAgaWYoYmx1cC5ncmFwaCRjdXRvZmYgPD0gY3V0b2ZmKSB7CiAgICBFKGJsdXAuZ3JhcGgkZ3JhcGgpJHdlaWdodCA8LSByYW5rKEUoYmx1cC5ncmFwaCRncmFwaCkkbXIpXigxLzQpCiAgICBwbG90KGJsdXAuZ3JhcGgkZ3JhcGgsCiAgICAgICAgIGxheW91dCA9IGxheW91dF93aXRoX2trLCAKICAgICAgICAgdmVydGV4LmxhYmVsID0gI2lmZWxzZShpcy5uYShWKGJsdXAuZ3JhcGgkZ3JhcGgpJGdlbmUpfFYoYmx1cC5ncmFwaCRncmFwaCkkZ2VuZT09IiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBWKGJsdXAuZ3JhcGgkZ3JhcGgpJG5hbWUgLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIyAgIFYoYmx1cC5ncmFwaCRncmFwaCkkZ2VuZSksCiAgICAgICAgIHZlcnRleC5sYWJlbC5jZXg9MSwKICAgICAgICAgbWFpbj1wYXN0ZSgiTVIgY3V0b2ZmID0iLHN1YigiYmx1cC5tci5ncmFwaC4iLCIiLGJsdXAuZ3JhcGgkY3V0b2ZmLGZpeGVkPVQpKSkKICAgIHJtKGJsdXAuZ3JhcGgpCiAgICB9CiAgfSkKZGV2Lm9mZigpCmBgYA==